package com.xs.designpattern;

/**
 * 双重检查
 * @author xs
 */
public class ThreadSafeDoubleCheckLocking {
    private static volatile ThreadSafeDoubleCheckLocking instance;

    /**
     * 私有构造函数以防止客户端实例化。
     */
    private ThreadSafeDoubleCheckLocking() {
        // 防止通过反射调用实例化
        if (instance != null) {
            throw new IllegalStateException("Already initialized.");
        }
    }

    /**
     * 公共访问器。
     *
     * @return 类的一个实例
     */
    public static ThreadSafeDoubleCheckLocking getInstance() {
        // 局部变量将性能提高了 25% Joshua Bloch，《Effective Java，第二版》，第 14 页283-284
        ThreadSafeDoubleCheckLocking result = instance;
        // 检查单例实例是否已初始化，如果它已初始化，那么我们可以返回该实例。
        if (result == null) {
            // 它没有初始化，但我们不能确定，因为同时其他线程可能已经初始化了它。因此，为了确保我们需要锁定一个对象以实现互斥。
            synchronized (ThreadSafeDoubleCheckLocking.class) {
                // 再次将实例分配给局部变量，以检查它是否由其他线程初始化，而当前线程被阻止进入锁定区域。如果它已初始化，那么我们可以像之前的空检查一样返回之前创建的实例。
                result = instance;
                if (result == null) {
                    // 该实例尚未初始化，因此我们可以安全地（没有其他线程可以进入该区域）创建一个实例并将其设为我们的单例实例。
                    instance = result = new ThreadSafeDoubleCheckLocking();
                }
            }
        }
        return result;
    }
}
